/**
 * @file pulse_data.c
 * @brief 遥脉数据模块实现
 * @details 本文件实现了104协议的遥脉数据处理功能，包括脉冲数据点配置、
 *          脉冲数据、脉冲数据组等数据类型的序列化和反序列化操作。
 *          支持完整的数据转换和验证功能。
 * 
 * @author zyb
 * @date 2025-10-12
 * @version 1.0
 * 
 * @note 所有函数都遵循104协议规范，确保严格的数据处理
 * @warning 数据转换失败时应返回相应的错误码，便于上层处理
 * 
 * @see pulse_data.h
 * @see protocol_types.h
 * @see buffer_utils.h
 * @see time_utils.h
 */

#include "../include/pulse_data.h"
#include "../../common/types/include/protocol_types.h"
#include "../../../../../common/utils/include/buffer_utils.h"
#include "../../common/utils/include/time_utils.h"
#include "../../common/error/include/error_codes.h"
#include "../../common/utils/include/validation_utils.h"
#include "../../../../../common/logs/include/logger.h"
#include <string.h>
#include <stdlib.h>

// 定义模块名称
#define LOG_MODULE_NAME "PULSE_DATA"

/* ==================== 脉冲数据点配置处理函数实现 ==================== */

/**
 * @brief 脉冲数据点配置转换为字节数组
 * @details 将脉冲数据点配置结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param config 脉冲数据点配置结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_pulse_point_config
 * @see validate_pulse_point_config
 * @see buffer_write_u16
 * @see buffer_write_f32
 * @see buffer_write_string
 */
protocol_error_t pulse_point_config_to_bytes(const pulse_point_config_t* config,
                                           u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始转换脉冲数据点配置到字节数组: config=%p, buffer=%p, buffer_size=%u", 
              config, buffer, buffer_size);
    
    if (config == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证脉冲数据点配置 */
    if (!(config->point_id != 0)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据点ID: %u", config->point_id);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID验证通过: %u", config->point_id);
    
    /* 检查缓冲区大小 */
    u32 required_size = 2 + 64 + 4 + 4; /* 点号(2字节) + 名称(64字节) + 系数(4字节) + 偏移(4字节) */
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < %u", buffer_size, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小检查通过: %u >= %u", buffer_size, required_size);
    
    u32 offset = 0;
    
    /* 写入点号 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲数据点ID: %u, 偏移: %u", config->point_id, offset);
    buffer_write_u16(&buffer[offset], 0, config->point_id, 0);
    offset += 2;
    
    /* 写入名称 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲数据点名称: '%.*s', 偏移: %u", 63, config->name, offset);
    memcpy(&buffer[offset], config->name, 64);
    offset += 64;
    
    /* 写入系数 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲数据点系数: %f, 偏移: %u", config->coefficient, offset);
    buffer_write_f32(&buffer[offset], 0, config->coefficient, 0);
    offset += 4;
    
    /* 写入偏移 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲数据点偏移: %f, 偏移: %u", config->offset, offset);
    buffer_write_f32(&buffer[offset], 0, config->offset, 0);
    offset += 4;
    
    *actual_length = offset;
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据点配置成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为脉冲数据点配置
 * @details 将104协议规定的字节数组格式转换为脉冲数据点配置结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param config 脉冲数据点配置结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳脉冲数据点配置
 * 
 * @see pulse_point_config_to_bytes
 * @see validate_pulse_point_config
 * @see buffer_read_u16
 * @see buffer_read_f32
 * @see buffer_read_string
 */
protocol_error_t bytes_to_pulse_point_config(const u8* data, u32 length,
                                            pulse_point_config_t* config) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始转换字节数组到脉冲数据点配置: data=%p, length=%u, config=%p", 
              data, length, config);
    
    if (data == NULL || config == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    u32 required_size = 2 + 64 + 4 + 4; /* 点号(2字节) + 名称(64字节) + 系数(4字节) + 偏移(4字节) */
    if (length < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "数据长度不足: %u < %u", length, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "数据长度检查通过: %u >= %u", length, required_size);
    
    u32 offset = 0;
    
    /* 读取点号 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲数据点ID, 偏移: %u", offset);
    buffer_read_u16(&data[offset], 0, &config->point_id, 0);
    offset += 2;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID读取完成: %u", config->point_id);
    
    /* 读取名称 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲数据点名称, 偏移: %u", offset);
    memcpy(config->name, &data[offset], 64);
    config->name[63] = '\0'; /* 确保字符串结束 */
    offset += 64;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点名称读取完成: '%.*s'", 63, config->name);
    
    /* 读取系数 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲数据点系数, 偏移: %u", offset);
    buffer_read_f32(&data[offset], 0, &config->coefficient, 0);
    offset += 4;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点系数读取完成: %f", config->coefficient);
    
    /* 读取偏移 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲数据点偏移, 偏移: %u", offset);
    buffer_read_f32(&data[offset], 0, &config->offset, 0);
    offset += 4;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点偏移读取完成: %f", config->offset);
    
    /* 验证转换后的数据 */
    if (!(config->point_id != 0)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据点ID: %u", config->point_id);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID验证通过: %u", config->point_id);
    
    LOG_INFO(LOG_MODULE_NAME, "字节数组成功转换为脉冲数据点配置");
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证脉冲数据点配置
 * @details 验证脉冲数据点配置结构的完整性和有效性。
 *          检查点号、名称、系数和偏移的有效性。
 * 
 * @param config 脉冲数据点配置结构，不能为NULL
 * @return 验证结果
 *         - 1: 脉冲数据点配置有效
 *         - 0: 脉冲数据点配置无效
 * 
 * @note 验证点号、名称、系数和偏移的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_info_address_valid
 * @see is_normalized_value_valid
 * @see pulse_point_config_t
 */
int validate_pulse_point_config(const pulse_point_config_t* config) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证脉冲数据点配置: config=%p", config);
    
    if (config == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲数据点ID: %u", config->point_id);
    int point_id_valid = (config->point_id != 0);
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID验证结果: %s", point_id_valid ? "有效" : "无效");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲数据点系数: %f", config->coefficient);
    int coefficient_valid = (config->coefficient != 0.0f);
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点系数验证结果: %s", coefficient_valid ? "有效" : "无效");
    
    int result = (point_id_valid && coefficient_valid);
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据点配置验证结果: %s", result ? "有效" : "无效");
    return result;
}

/* ==================== 脉冲数据处理函数实现 ==================== */

/**
 * @brief 脉冲数据转换为字节数组
 * @details 将脉冲数据结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param pulse 脉冲数据结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_pulse_data
 * @see validate_pulse_data
 * @see buffer_write_u16
 * @see buffer_write_u32
 * @see buffer_write_f32
 * @see cp56time2a_to_bytes
 */
protocol_error_t pulse_data_to_bytes(const pulse_data_t* pulse,
                                    u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始转换脉冲数据到字节数组: pulse=%p, buffer=%p, buffer_size=%u", 
              pulse, buffer, buffer_size);
    
    if (pulse == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证脉冲数据 */
    if (pulse->point_id == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据点ID: %u", pulse->point_id);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID验证通过: %u", pulse->point_id);
    
    if (!is_cp56time2a_valid(&pulse->timestamp)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的时间戳");
        return PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳验证通过");
    
    /* 检查缓冲区大小 */
    u32 required_size = 2 + 4 + 4 + 7; /* 点号(2字节) + 计数值(4字节) + 计算值(4字节) + 时间戳(7字节) */
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < %u", buffer_size, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小检查通过: %u >= %u", buffer_size, required_size);
    
    u32 offset = 0;
    
    /* 写入点号 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲数据点ID: %u, 偏移: %u", pulse->point_id, offset);
    buffer_write_u16(&buffer[offset], 0, pulse->point_id, 0);
    offset += 2;
    
    /* 写入脉冲计数值 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲计数值: %u, 偏移: %u", pulse->pulse_count, offset);
    buffer_write_u32(&buffer[offset], 0, pulse->pulse_count, 0);
    offset += 4;
    
    /* 写入计算后的值 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入计算后的值: %f, 偏移: %u", pulse->calculated_value, offset);
    buffer_write_f32(&buffer[offset], 0, pulse->calculated_value, 0);
    offset += 4;
    
    /* 写入时间戳 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入时间戳, 偏移: %u", offset);
    memcpy(&buffer[offset], &pulse->timestamp, 7);
    offset += 7;
    
    *actual_length = offset;
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为脉冲数据
 * @details 将104协议规定的字节数组格式转换为脉冲数据结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param pulse 脉冲数据结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳脉冲数据
 * 
 * @see pulse_data_to_bytes
 * @see validate_pulse_data
 * @see buffer_read_u16
 * @see buffer_read_u32
 * @see buffer_read_f32
 * @see bytes_to_cp56time2a
 */
protocol_error_t bytes_to_pulse_data(const u8* data, u32 length,
                                   pulse_data_t* pulse) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始转换字节数组到脉冲数据: data=%p, length=%u, pulse=%p", 
              data, length, pulse);
    
    if (data == NULL || pulse == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    u32 required_size = 2 + 4 + 4 + 7; /* 点号(2字节) + 计数值(4字节) + 计算值(4字节) + 时间戳(7字节) */
    if (length < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "数据长度不足: %u < %u", length, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "数据长度检查通过: %u >= %u", length, required_size);
    
    u32 offset = 0;
    
    /* 读取点号 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲数据点ID, 偏移: %u", offset);
    buffer_read_u16(&data[offset], 0, &pulse->point_id, 0);
    offset += 2;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID读取完成: %u", pulse->point_id);
    
    /* 读取脉冲计数值 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲计数值, 偏移: %u", offset);
    buffer_read_u32(&data[offset], 0, &pulse->pulse_count, 0);
    offset += 4;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲计数值读取完成: %u", pulse->pulse_count);
    
    /* 读取计算后的值 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取计算后的值, 偏移: %u", offset);
    buffer_read_f32(&data[offset], 0, &pulse->calculated_value, 0);
    offset += 4;
    LOG_DEBUG(LOG_MODULE_NAME, "计算后的值读取完成: %f", pulse->calculated_value);
    
    /* 读取时间戳 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取时间戳, 偏移: %u", offset);
    memcpy(&pulse->timestamp, &data[offset], 7);
    offset += 7;
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳读取完成");
    
    /* 验证转换后的数据 */
    if (pulse->point_id == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据点ID: %u", pulse->point_id);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID验证通过: %u", pulse->point_id);
    
    if (!is_cp56time2a_valid(&pulse->timestamp)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的时间戳");
        return PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳验证通过");
    
    LOG_INFO(LOG_MODULE_NAME, "字节数组成功转换为脉冲数据");
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证脉冲数据
 * @details 验证脉冲数据结构的完整性和有效性。
 *          检查点号、计数值、计算值和时间戳的有效性。
 * 
 * @param pulse 脉冲数据结构，不能为NULL
 * @return 验证结果
 *         - 1: 脉冲数据有效
 *         - 0: 脉冲数据无效
 * 
 * @note 验证点号、计数值、计算值和时间戳的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_info_address_valid
 * @see is_normalized_value_valid
 * @see is_short_float_valid
 * @see is_cp56time2a_valid
 * @see pulse_data_t
 */
int validate_pulse_data(const pulse_data_t* pulse) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证脉冲数据: pulse=%p", pulse);
    
    if (pulse == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲数据点ID: %u", pulse->point_id);
    int point_id_valid = (pulse->point_id != 0);
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据点ID验证结果: %s", point_id_valid ? "有效" : "无效");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证时间戳");
    int timestamp_valid = is_cp56time2a_valid(&pulse->timestamp);
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳验证结果: %s", timestamp_valid ? "有效" : "无效");
    
    int result = (point_id_valid && timestamp_valid);
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据验证结果: %s", result ? "有效" : "无效");
    return result;
}

/* ==================== 脉冲数据组处理函数实现 ==================== */

/**
 * @brief 脉冲数据组转换为字节数组
 * @details 将脉冲数据组结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param group 脉冲数据组结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_pulse_data_group
 * @see validate_pulse_data_group
 * @see buffer_write_u32
 * @see pulse_data_to_bytes
 */
protocol_error_t pulse_data_group_to_bytes(const pulse_data_group_t* group,
                                         u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始转换脉冲数据组到字节数组: group=%p, buffer=%p, buffer_size=%u", 
              group, buffer, buffer_size);
    
    if (group == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证脉冲数据组 */
    if (!(group->count > 0 && group->count <= 1000)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据组计数: %u", group->count);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据组计数验证通过: %u", group->count);
    
    /* 检查缓冲区大小 */
    u32 required_size = 4 + (group->count * 17); /* 计数(4字节) + 每个脉冲数据(17字节) */
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < %u", buffer_size, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小检查通过: %u >= %u", buffer_size, required_size);
    
    u32 offset = 0;
    
    /* 写入数据个数 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入脉冲数据组计数: %u, 偏移: %u", group->count, offset);
    buffer_write_u32(&buffer[offset], 0, group->count, 0);
    offset += 4;
    
    /* 写入每个脉冲数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "开始写入脉冲数据，数量: %u", group->count);
    for (u32 i = 0; i < group->count; i++) {
        LOG_DEBUG(LOG_MODULE_NAME, "写入第 %u 个脉冲数据, 偏移: %u", i + 1, offset);
        u32 data_length;
        protocol_error_t result = pulse_data_to_bytes(&group->data[i], &buffer[offset], 
                                                    buffer_size - offset, &data_length);
        if (result != PROTOCOL_SUCCESS) {
            LOG_ERROR(LOG_MODULE_NAME, "第 %u 个脉冲数据转换失败: %d", i + 1, result);
            return result;
        }
        offset += data_length;
        LOG_DEBUG(LOG_MODULE_NAME, "第 %u 个脉冲数据写入完成，长度: %u", i + 1, data_length);
    }
    
    *actual_length = offset;
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据组成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为脉冲数据组
 * @details 将104协议规定的字节数组格式转换为脉冲数据组结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param group 脉冲数据组结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳脉冲数据组
 * 
 * @see pulse_data_group_to_bytes
 * @see validate_pulse_data_group
 * @see buffer_read_u32
 * @see bytes_to_pulse_data
 */
protocol_error_t bytes_to_pulse_data_group(const u8* data, u32 length,
                                          pulse_data_group_t* group) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始转换字节数组到脉冲数据组: data=%p, length=%u, group=%p", 
              data, length, group);
    
    if (data == NULL || group == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    if (length < 4) { /* 至少需要计数(4字节) */
        LOG_ERROR(LOG_MODULE_NAME, "数据长度不足: %u < 4", length);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    u32 offset = 0;
    
    /* 读取数据个数 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取脉冲数据组计数, 偏移: %u", offset);
    buffer_read_u32(&data[offset], 0, &group->count, 0);
    offset += 4;
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据组计数读取完成: %u", group->count);
    
    /* 检查数据个数是否合理 */
    if (group->count == 0 || group->count > 1000) { /* 限制最大数据个数 */
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据组计数: %u", group->count);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据组计数验证通过: %u", group->count);
    
    /* 检查剩余数据长度 */
    u32 required_size = group->count * 17; /* 每个脉冲数据17字节 */
    if (length - offset < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "剩余数据长度不足: %u < %u", length - offset, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "剩余数据长度检查通过: %u >= %u", length - offset, required_size);
    
    /* 分配内存 */
    LOG_DEBUG(LOG_MODULE_NAME, "分配脉冲数据内存，大小: %u * %zu", group->count, sizeof(pulse_data_t));
    group->data = (pulse_data_t*)malloc(group->count * sizeof(pulse_data_t));
    if (group->data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败");
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据内存分配成功: %p", group->data);
    
    group->max_count = group->count;
    
    /* 读取每个脉冲数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "开始读取脉冲数据，数量: %u", group->count);
    for (u32 i = 0; i < group->count; i++) {
        LOG_DEBUG(LOG_MODULE_NAME, "读取第 %u 个脉冲数据, 偏移: %u", i + 1, offset);
        protocol_error_t result = bytes_to_pulse_data(&data[offset], 17, &group->data[i]);
        if (result != PROTOCOL_SUCCESS) {
            LOG_ERROR(LOG_MODULE_NAME, "第 %u 个脉冲数据转换失败: %d", i + 1, result);
            free(group->data);
            group->data = NULL;
            group->count = 0;
            group->max_count = 0;
            return result;
        }
        offset += 17;
        LOG_DEBUG(LOG_MODULE_NAME, "第 %u 个脉冲数据读取完成", i + 1);
    }
    
    /* 验证转换后的数据 */
    if (!(group->count > 0 && group->count <= 1000)) {
        LOG_ERROR(LOG_MODULE_NAME, "转换后数据验证失败，计数: %u", group->count);
        free(group->data);
        group->data = NULL;
        group->count = 0;
        group->max_count = 0;
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "转换后数据验证通过，计数: %u", group->count);
    
    LOG_INFO(LOG_MODULE_NAME, "字节数组成功转换为脉冲数据组，数据数量: %u", group->count);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证脉冲数据组
 * @details 验证脉冲数据组结构的完整性和有效性。
 *          检查数据个数、数据数组和每个数据的有效性。
 * 
 * @param group 脉冲数据组结构，不能为NULL
 * @return 验证结果
 *         - 1: 脉冲数据组有效
 *         - 0: 脉冲数据组无效
 * 
 * @note 验证数据个数、数据数组和每个数据的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_pulse_count_valid
 * @see validate_pulse_data
 * @see pulse_data_group_t
 */
int validate_pulse_data_group(const pulse_data_group_t* group) {
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证脉冲数据组: group=%p", group);
    
    if (group == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲数据组计数: %u", group->count);
    if (!(group->count > 0 && group->count <= 1000)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的脉冲数据组计数: %u", group->count);
        return 0;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据组计数验证通过: %u", group->count);
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲数据数组指针: %p", group->data);
    if (group->data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "脉冲数据数组指针为空");
        return 0;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "脉冲数据数组指针验证通过");
    
    /* 验证每个脉冲数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证每个脉冲数据，数量: %u", group->count);
    for (u32 i = 0; i < group->count; i++) {
        LOG_DEBUG(LOG_MODULE_NAME, "验证第 %u 个脉冲数据", i + 1);
        if (!validate_pulse_data(&group->data[i])) {
            LOG_ERROR(LOG_MODULE_NAME, "第 %u 个脉冲数据验证失败", i + 1);
            return 0;
        }
        LOG_DEBUG(LOG_MODULE_NAME, "第 %u 个脉冲数据验证通过", i + 1);
    }
    
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据组验证通过，数据数量: %u", group->count);
    return 1;
}

/* ==================== 辅助函数实现 ==================== */

/**
 * @brief 获取脉冲数据点配置大小
 * @details 获取脉冲数据点配置结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 脉冲数据点配置大小（字节）
 * 
 * @note 脉冲数据点配置大小：74字节（点号2字节 + 名称64字节 + 系数4字节 + 偏移4字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_pulse_data_size
 * @see get_pulse_data_group_size
 * @see pulse_point_config_t
 */
u32 get_pulse_point_config_size(void) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取脉冲数据点配置大小");
    u32 size = 74; /* 点号(2字节) + 名称(64字节) + 系数(4字节) + 偏移(4字节) */
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据点配置大小: %u 字节", size);
    return size;
}

/**
 * @brief 获取脉冲数据大小
 * @details 获取脉冲数据结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 脉冲数据大小（字节）
 * 
 * @note 脉冲数据大小：17字节（点号2字节 + 计数值4字节 + 计算值4字节 + 时间戳7字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_pulse_point_config_size
 * @see get_pulse_data_group_size
 * @see pulse_data_t
 */
u32 get_pulse_data_size(void) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取脉冲数据大小");
    u32 size = 17; /* 点号(2字节) + 计数值(4字节) + 计算值(4字节) + 时间戳(7字节) */
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据大小: %u 字节", size);
    return size;
}

/**
 * @brief 获取脉冲数据组大小
 * @details 获取脉冲数据组结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @param count 数据个数
 * @return 脉冲数据组大小（字节）
 * 
 * @note 脉冲数据组大小：4字节 + (数据个数 * 17字节)
 * @warning 此函数是线程安全的
 * 
 * @see get_pulse_point_config_size
 * @see get_pulse_data_size
 * @see pulse_data_group_t
 */
u32 get_pulse_data_group_size(u32 count) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取脉冲数据组大小: count=%u", count);
    u32 size = 4 + (count * 17); /* 计数(4字节) + 每个脉冲数据(17字节) */
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据组大小: %u 字节 (数据个数: %u)", size, count);
    return size;
}

/* ==================== 脉冲数据计算函数实现 ==================== */

/**
 * @brief 计算脉冲数据值
 * @details 根据脉冲计数值、系数和偏移计算实际值。
 *          计算公式：实际值 = 计数值 * 系数 + 偏移
 * 
 * @param pulse_count 脉冲计数值
 * @param coefficient 系数
 * @param offset 偏移
 * @return 计算后的实际值
 * 
 * @note 计算公式：实际值 = 计数值 * 系数 + 偏移
 * @warning 系数和偏移必须为有效值
 * 
 * @see calculate_pulse_data_from_config
 * @see is_short_float_valid
 */
float calculate_pulse_data_value(u32 pulse_count, float coefficient, float offset) {
    LOG_DEBUG(LOG_MODULE_NAME, "计算脉冲数据值: pulse_count=%u, coefficient=%f, offset=%f", 
              pulse_count, coefficient, offset);
    float result = (float)pulse_count * coefficient + offset;
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据值计算完成: %f", result);
    return result;
}

/**
 * @brief 根据配置计算脉冲数据值
 * @details 根据脉冲数据点配置计算脉冲数据值。
 *          使用配置中的系数和偏移进行计算。
 * 
 * @param pulse_count 脉冲计数值
 * @param config 脉冲数据点配置，不能为NULL
 * @return 计算后的实际值
 * 
 * @note 使用配置中的系数和偏移进行计算
 * @warning 配置指针不能为NULL
 * 
 * @see calculate_pulse_data_value
 * @see validate_pulse_point_config
 */
float calculate_pulse_data_from_config(u32 pulse_count, const pulse_point_config_t* config) {
    LOG_DEBUG(LOG_MODULE_NAME, "根据配置计算脉冲数据值: pulse_count=%u, config=%p", 
              pulse_count, config);
    
    if (config == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return 0.0f;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "使用配置计算: coefficient=%f, offset=%f", 
              config->coefficient, config->offset);
    float result = calculate_pulse_data_value(pulse_count, config->coefficient, config->offset);
    LOG_INFO(LOG_MODULE_NAME, "根据配置计算脉冲数据值完成: %f", result);
    return result;
}

/* ==================== 脉冲数据验证函数实现 ==================== */

/**
 * @brief 验证脉冲点号
 * @details 验证脉冲点号是否在有效范围内。
 *          点号范围：1-65535
 * 
 * @param point_id 脉冲点号
 * @return 验证结果
 *         - 1: 点号有效
 *         - 0: 点号无效
 * 
 * @note 点号范围：1-65535
 * @warning 点号不能为0
 * 
 * @see is_normalized_value_valid
 * @see is_normalized_value_valid
 */
int is_pulse_point_id_valid(u16 point_id) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲点号: point_id=%u", point_id);
    int valid = (point_id > 0);
    LOG_INFO(LOG_MODULE_NAME, "脉冲点号验证结果: %s", valid ? "有效" : "无效");
    return valid;
}

/**
 * @brief 验证脉冲系数
 * @details 验证脉冲系数是否在有效范围内。
 *          系数范围：-1000.0 到 1000.0
 * 
 * @param coefficient 脉冲系数
 * @return 验证结果
 *         - 1: 系数有效
 *         - 0: 系数无效
 * 
 * @note 系数范围：-1000.0 到 1000.0
 * @warning 系数不能为NaN或无穷大
 * 
 * @see is_info_address_valid
 * @see is_normalized_value_valid
 */
int is_pulse_coefficient_valid(float coefficient) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲系数: coefficient=%f", coefficient);
    int valid = (coefficient >= -1000.0f && coefficient <= 1000.0f && 
                 coefficient != 0.0f);
    LOG_INFO(LOG_MODULE_NAME, "脉冲系数验证结果: %s", valid ? "有效" : "无效");
    return valid;
}

/**
 * @brief 验证脉冲偏移
 * @details 验证脉冲偏移是否在有效范围内。
 *          偏移范围：-10000.0 到 10000.0
 * 
 * @param offset 脉冲偏移
 * @return 验证结果
 *         - 1: 偏移有效
 *         - 0: 偏移无效
 * 
 * @note 偏移范围：-10000.0 到 10000.0
 * @warning 偏移不能为NaN或无穷大
 * 
 * @see is_info_address_valid
 * @see is_normalized_value_valid
 */
int is_pulse_offset_valid(float offset) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲偏移: offset=%f", offset);
    int valid = (offset >= -10000.0f && offset <= 10000.0f);
    LOG_INFO(LOG_MODULE_NAME, "脉冲偏移验证结果: %s", valid ? "有效" : "无效");
    return valid;
}

/**
 * @brief 验证脉冲计数值
 * @details 验证脉冲计数值是否在有效范围内。
 *          计数值范围：0-4294967295
 * 
 * @param pulse_count 脉冲计数值
 * @return 验证结果
 *         - 1: 计数值有效
 *         - 0: 计数值无效
 * 
 * @note 计数值范围：0-4294967295
 * @warning 计数值不能为负数
 * 
 * @see is_short_float_valid
 * @see is_info_address_valid
 */
int is_pulse_count_valid(u32 pulse_count) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲计数值: pulse_count=%u", pulse_count);
    int valid = (pulse_count <= 4294967295U);
    LOG_INFO(LOG_MODULE_NAME, "脉冲计数值验证结果: %s", valid ? "有效" : "无效");
    return valid;
}

/**
 * @brief 验证脉冲计算值
 * @details 验证脉冲计算值是否在有效范围内。
 *          计算值范围：-1000000.0 到 1000000.0
 * 
 * @param calculated_value 脉冲计算值
 * @return 验证结果
 *         - 1: 计算值有效
 *         - 0: 计算值无效
 * 
 * @note 计算值范围：-1000000.0 到 1000000.0
 * @warning 计算值不能为NaN或无穷大
 * 
 * @see is_normalized_value_valid
 * @see is_normalized_value_valid
 */
int is_pulse_calculated_value_valid(float calculated_value) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲计算值: calculated_value=%f", calculated_value);
    int valid = (calculated_value >= -1000000.0f && calculated_value <= 1000000.0f);
    LOG_INFO(LOG_MODULE_NAME, "脉冲计算值验证结果: %s", valid ? "有效" : "无效");
    return valid;
}

/**
 * @brief 验证脉冲数据组计数
 * @details 验证脉冲数据组计数是否在有效范围内。
 *          计数范围：1-1000
 * 
 * @param count 脉冲数据组计数
 * @return 验证结果
 *         - 1: 计数有效
 *         - 0: 计数无效
 * 
 * @note 计数范围：1-1000
 * @warning 计数不能为0或过大
 * 
 * @see validate_pulse_data_group
 * @see is_info_address_valid
 */
int is_pulse_group_count_valid(u32 count) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证脉冲数据组计数: count=%u", count);
    int valid = (count > 0 && count <= 1000);
    LOG_INFO(LOG_MODULE_NAME, "脉冲数据组计数验证结果: %s", valid ? "有效" : "无效");
    return valid;
}
